/* Yet Another Experimental Software Renderer
 *
 * Copyright (c) 2010 Pawel "Hery" Dziepak
 */

#ifndef PIPELINE_H_
#define PIPELINE_H_

#include "vertex_input.h"
#include "input_assembler.h"
#include "pixel_shader.h"
#include "hull_shader.h"
#include "domain_shader.h"
#include "vertex_shader.h"
#include "tessellator.h"
#include "geometry_shader.h"
#include "rasterizer.h"
#include "pixel_shader.h"
#include "output_merger.h"

#include "vectors.h"

#include <vector>

namespace yaesr {
	class pipeline {
	public:
		pipeline() : vi(NULL), ia(NULL), vs(NULL), hs(NULL), ts(NULL), ds(NULL), gs(NULL), ra(NULL), ps(NULL), om(NULL), po(NULL) { }

		void set_input(vertex_input *x) {
			Assert(x != NULL);

			vi = x;
			vi->set_next(ia);
		}

		void set_input_assembler(input_assembler *x) {
			Assert(x != NULL);

			ia = x;
		}

		void set_vertex_shader(vertex_shader *x) {
			Assert(x != NULL);

			vs = x;
		}

		void set_hull_shader(hull_shader *x) {
			Assert(x != NULL);

			hs = x;
		}

		void set_tessellator(tessellator *x) {
			Assert(x != NULL);

			ts = x;
		}

		void set_domain_shader(domain_shader *x) {
			Assert(x != NULL);

			ds = x;
		}

		void set_geometry_shader(geometry_shader *x) {
			Assert(x != NULL);

			gs = x;
		}

		void set_rasterizer(rasterizer *x) {
			Assert(x != NULL);

			ra = x;
		}

		void set_pixel_shader(pixel_shader *x) {
			Assert(x != NULL);

			ps = x;
		}

		void set_output_merger(output_merger *x) {
			Assert(x != NULL);

			om = x;
		}

		void set_output(pixel_output *x) {
			Assert(x != NULL);

			po = x;
		}

		void launch() {
			if (!ia || !vs || !hs || !ts || !ds || !gs || !ra || !ps || !om || !po)
				Error("Attempt to launch not configured pipeline");

			if (vi)
				vi->set_next(ia);

			ia->set_vertex_shader(vs);
			ia->set_hull_shader(hs);
			ia->set_tessellator(ts);
			ia->set_domain_shader(ds);
			ia->set_geometry_shader(gs);

			ra->set_pixel_shader(ps);

			om->set_next(po);
		}

	private:
		vertex_input *vi;
		input_assembler *ia;
		vertex_shader *vs;
		hull_shader *hs;
		tessellator *ts;
		domain_shader *ds;
		geometry_shader *gs;
		rasterizer *ra;
		pixel_shader *ps;
		output_merger *om;
		pixel_output *po;
	};
}

#endif